#include "OriginPCH.h"
#include "OpenGLVertexArray.h"
#include <glad/glad.h>

namespace Origin
{
	static GLenum ShaderDataTypeToOpenGLBaseType(ShaderDataType type)
	{
		switch (type)
		{
		case Origin::ShaderDataType::Float:    return GL_FLOAT;
		case Origin::ShaderDataType::Float2:   return GL_FLOAT;
		case Origin::ShaderDataType::Float3:   return GL_FLOAT;
		case Origin::ShaderDataType::Float4:   return GL_FLOAT;
		case Origin::ShaderDataType::Mat3:     return GL_FLOAT;
		case Origin::ShaderDataType::Mat4:     return GL_FLOAT;
		case Origin::ShaderDataType::Int:      return GL_INT;
		case Origin::ShaderDataType::Int2:     return GL_INT;
		case Origin::ShaderDataType::Int3:     return GL_INT;
		case Origin::ShaderDataType::Int4:     return GL_INT;
		case Origin::ShaderDataType::Bool:     return GL_BOOL;
		}

		ORIGIN_CORE_ASSERT(false, "Unknown ShaderDataType!");
		return 0;
	}

	OpenGLVertexArray::OpenGLVertexArray()
	{
		glCreateVertexArrays(1, &_rendererID);
	}

	OpenGLVertexArray::~OpenGLVertexArray()
	{
		glDeleteVertexArrays(1, &_rendererID);
	}

	void OpenGLVertexArray::Bind() const
	{
		glBindVertexArray(_rendererID);
	}

	void OpenGLVertexArray::Unbind() const
	{
		glBindVertexArray(0);
	}

	void OpenGLVertexArray::AddVertexBuffer(const std::shared_ptr<VertexBuffer>& vertexBuffer)
	{
		glBindVertexArray(_rendererID); // bind VAO
		vertexBuffer->Bind(); //bind buffer, bind data

		uint32_t index = 0;
		const auto& layout = vertexBuffer->GetLayout();

		for (const auto& element: layout)
		{
			glEnableVertexAttribArray(index);
			glVertexAttribPointer(index,
				element.GetComponentCount(),
				ShaderDataTypeToOpenGLBaseType(element.type),
				element.normalized ? GL_TRUE : GL_FALSE,
				layout.GetStride(),
				(const void*)(intptr_t)element.offset);
			++index;
		}
		_vertexBuffers.push_back(vertexBuffer);
	}

	void OpenGLVertexArray::SetIndexBuffer(const std::shared_ptr<IndexBuffer>& indexBuffer)
	{
		glBindVertexArray(_rendererID);
		indexBuffer->Bind();
		_indexBuffer = indexBuffer;
	}

}